<?php

Raise::load('core.RaiseObject');
Raise::load('db.sql.RaiseDbSqlIdentifier');
Raise::load('core.RaiseTypedCollection');

/**
 * RaiseDbSqlWhere
 * represents a SQL where condition
 *
 * @author Sam-Mauris Yong / hellclanner at live dot com
 * @license http://www.opensource.org/licenses/bsd-license New BSD License
 * @package phpraise.db.sql
 * @since 1.2
 */
class RaiseDbSqlWhere extends RaiseObject {

    /**
     * The operator for this condition
     * @var string
     */
    private $operator;
    
    /**
     * The left operand of this SQL condition statement
     * @var RaiseDbSqlIdentifier|mixed
     */
    private $leftOperand;
    
    /**
     * The right operand of this SQL condition statement
     * @var RaiseDbSqlIdentifier|mixed
     */
    private $rightOperand;
    
    /**
     * The collection of sub conditions
     * @var RaiseTypedCollection
     */
    private $subConditions;

    /**
     * Create a new RaiseDbSqlCondition
     * @param string $operator (optional) The operator for this condition. If
     *          not set, and there are sub conditions to this condition, the
     *          default operator is AND. If it is not set and there are no sub
     *          conditions, the default operator is equals (=).
     * @param RaiseDbSqlIdentifier|mixed $left (optional) The left operand
     * @param RaiseDbSqlIdentifier|mixed $right (optional) The right operand
     */
    function __construct($operator = null, $left = null, $right = null) {
        $this->operator($operator);
        $this->leftOperand($left);
        $this->rightOperand($right);
        $this->subConditions = new RaiseTypedCollection('RaiseDbSqlWhere');
    }

    /**
     * Get or set the operator for this SQL condition.
     * @param string $o (optional) Set the new operator
     * @return string
     */
    public function operator($o = null) {
        if (func_num_args() == 1) {
            $this->operator = $o;
        }
        return $this->operator;
    }

    /**
     * Get or set the left operand of this SQL condition statement. Ignored if
     * there is any item in the sub conditions collection
     * @param RaiseDbSqlIdentifier|mixed $l (optional) The new left operand value
     * @return RaiseDbSqlIdentifier|mixed
     */
    public function leftOperand($l = null) {
        if (func_num_args() == 1) {
            $this->leftOperand = $l;
        }
        return $this->leftOperand;
    }

    /**
     * Get or set the right operand of this SQL condition statement. Ignored if
     * there is any item in the sub conditions collection
     * @param RaiseDbSqlIdentifier|RaiseTypedCollection|mixed $r (optional) The new right operand value
     * @return RaiseDbSqlIdentifier|RaiseTypedCollection|mixed
     */
    public function rightOperand($r = null) {
        if (func_num_args() == 1) {
            $this->rightOperand = $r;
        }
        return $this->rightOperand;
    }

    /**
     * Get or set the sub conditions of this statement
     * @return RaiseTypedCollection
     */
    public function subConditions() {
        return $this->subConditions;
    }

    /**
     * Generate the SQL portion of this condition or its subconditions
     * @return string
     */
    public function __toString() {
        $left = $this->leftOperand;
        $right = $this->rightOperand;
        if(is_object($left)){
            $left = $left->__toString();
        }
        if(is_object($right)){
            $right = $right->__toString();
        }
        $left = trim($left);
        $right = trim($right);
        if ($this->subConditions->count() > 0) {
            if ($this->operator == null) {
                $this->operator = ' AND';
            }
            $c = array();
            foreach ($this->subConditions as $a) {
                $s = $a->__toString();
                if ($s) {
                    $c[] = $s;
                }
            }
            return '(' . implode(' ' . $this->operator . ' ', $c) . ')';
        } else {
            if ($left && $right) {
                if ($this->operator == null) {
                    $this->operator = '=';
                }
                return '(' . $left . ' ' . $this->operator . ' ' . $right . ')';
            }
        }
        return '';
    }

}